﻿using System.ComponentModel;
using System.Windows;
using Gavel.Common.Component.Helper;
using Gavel.Common.Utilities.Const;
using Gavel.ModLink.Model;

namespace Gavel.ModLink.ViewModel;

/// <summary>
/// 寄存器配置视图模型
/// </summary>
public class OptionsViewModel : INotifyPropertyChanged
{
    /// <summary>
    /// 属性修改事件
    /// </summary>
    public event PropertyChangedEventHandler? PropertyChanged;

    /// <summary>
    /// 视图可见性
    /// </summary>
    private Visibility _showSendView = Visibility.Collapsed;

    /// <summary>
    /// 视图可见性
    /// </summary>
    public Visibility ShowSendView
    {
        get => _showSendView;
        set
        {
            _showSendView = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ShowSendView)));
        }
    }
    
    /// <summary>
    /// 协议类型
    /// </summary>
    private Pair<ProtocolType, string> _protocol = Protocols.First();

    /// <summary>
    /// 协议类型
    /// </summary>
    public Pair<ProtocolType, string> Protocol
    {
        get => _protocol;
        set
        {
            _protocol = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Protocol)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ShowEndian)));
        }
    }

    /// <summary>
    /// 协议列表
    /// </summary>
    public static List<Pair<ProtocolType, string>> Protocols =>
    [
        new(ProtocolType.Tcp, "TCP协议"),
        new(ProtocolType.Rtu, "RTU协议")
    ];

    /// <summary>
    /// 功能码
    /// </summary>
    public Pair<FunctionType, string> Function { get; set; } = Functions.First();

    /// <summary>
    /// 功能码列表
    /// </summary>
    public static List<Pair<FunctionType, string>> Functions =>
    [
        new(FunctionType.ReadHolding, "03 读保持寄存器"),
        new(FunctionType.ReadInput, "04 读输入寄存器")
    ];

    /// <summary>
    /// 从机地址
    /// </summary>
    private byte _slave = 1;

    /// <summary>
    /// 从机地址
    /// </summary>
    public byte Slave
    {
        get => _slave;
        set
        {
            _slave = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Slave)));
        }
    }

    /// <summary>
    /// 寄存器起始地址
    /// </summary>
    private ushort _startAddr;

    /// <summary>
    /// 寄存器起始地址
    /// </summary>
    public ushort StartAddr
    {
        get => _startAddr;
        set
        {
            _startAddr = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StartAddr)));
        }
    }

    /// <summary>
    /// 寄存器数量
    /// </summary>
    private byte _count = 1;

    /// <summary>
    /// 寄存器数量
    /// </summary>
    public byte Count
    {
        get => _count;
        set
        {
            switch (value)
            {
                case 0:
                    NotifyHelper.Instance.Warning("寄存器数量不能为0");
                    return;
                case > 125:
                    NotifyHelper.Instance.Warning("寄存器数量不能超过125");
                    return;
                default:
                    _count = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
                    break;
            }
        }
    }

    /// <summary>
    /// 自动读取
    /// </summary>
    private bool _isAuto;

    /// <summary>
    /// 自动读取
    /// </summary>
    public bool IsAuto
    {
        get => _isAuto;
        set
        {
            _isAuto = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsAuto)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(InputEnable)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SendEnable)));
        }
    }

    /// <summary>
    /// 自动读取周期
    /// </summary>
    public Pair<ushort, string> Period { get; set; } = Periods.First();

    /// <summary>
    /// 自动读取周期键值对
    /// </summary>
    public static List<Pair<ushort, string>> Periods =>
    [
        new(1, "1 秒"),
        new(3, "3 秒"),
        new(5, "5 秒"),
        new(10, "10 秒")
    ];

    /// <summary>
    /// 启用输入
    /// </summary>
    public bool InputEnable => IsAuto == false;

    /// <summary>
    /// 是否小端
    /// </summary>
    private bool _isLittleEndian = true;

    /// <summary>
    /// 是否小端
    /// </summary>
    public bool IsLittleEndian
    {
        get => _isLittleEndian;
        set
        {
            _isLittleEndian = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLittleEndian)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(EndianName)));
        }
    }

    /// <summary>
    /// CRC大小端可见性
    /// </summary>
    public Visibility ShowEndian => Protocol.Key == ProtocolType.Rtu ? Visibility.Visible : Visibility.Collapsed;

    /// <summary>
    /// 大小端名称
    /// </summary>
    public string EndianName => IsLittleEndian ? "CRC小端" : "CRC大端";

    /// <summary>
    /// 大小端类型
    /// </summary>
    public Endian Endian => IsLittleEndian ? Endian.Little : Endian.Big;
    
    /// <summary>
    /// 可发送
    /// </summary>
    private bool _canSend = true;

    /// <summary>
    /// 可发送
    /// </summary>
    public bool CanSend
    {
        get => _canSend;
        set
        {
            _canSend = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SendEnable)));
        }
    }

    /// <summary>
    /// 启用手动发送
    /// </summary>
    public bool SendEnable => InputEnable && CanSend;
}